package com.psychologyCommunity.Community.Contoller;

import com.psychologyCommunity.Community.entity.*;
import com.psychologyCommunity.Community.event.EventProducer;
import com.psychologyCommunity.Community.service.*;
import com.psychologyCommunity.Community.util.CommunityUtil;
import com.psychologyCommunity.Community.util.HostHolder;
import com.psychologyCommunity.Community.util.RedisKeyUtil;
import com.sun.org.apache.xpath.internal.operations.Mod;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.*;

import static com.psychologyCommunity.Community.util.CommunityConstance.*;

@Controller
@RequestMapping("/discuss")
public class DiscussPostController {
    //先把service注入进来
    @Autowired
    private DiscussPostService discussPostService;
    @Autowired //当前用户也要注入进来
    private HostHolder hostHolder;
    @Autowired
    private EventProducer eventProducer;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ElasticsearchService elasticsearchService;

    @RequestMapping(path = "/add",method = RequestMethod.POST)
    @ResponseBody
    //浏览器只用给我们传title 和content ,一个新帖子表里面其他数据都是自动生成（之前写过）
    public String addDiscussPost(String title,String content){
        User user=hostHolder.getUser();
        if(user==null){ //如果当前用户为空，就是没登录给页面返回一个异步的提示（json格式的字符串）
            return CommunityUtil.getJSONString(403,"你还没有登录啊！");
        }
        //创建一个帖子插入
        DiscussPost curPost=new DiscussPost();
        curPost.setUser_id(user.getId());//从当前用户拿id-->之前 出现bug的原因 --》拿到userId 确误放到了帖子的Id 导致userId默认取0，没有来源
//        curPost.setUser_id(108);
        curPost.setTitle(title);
        curPost.setContent(content);
        curPost.setCreateTime(new Date());
        discussPostService.addDiscussPost(curPost);

        //触发发帖事件
        Event event=new Event()
                .setTopic(TOPIC_PUBLISH)
                .setUserId(user.getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityType(curPost.getId());
        eventProducer.fireEvent(event);

        //计算帖子的分数
        String postScoreKey = RedisKeyUtil.getPostScoreKey();
        //用Set而不用队列的原因：存在缓存中的数据 无需排序并且要去重-- 可能这个用户点赞由清除又点赞进行多次，那么重复数据算起来没有意义，
        redisTemplate.opsForSet().add(postScoreKey,curPost.getId());//添加帖子的时候给他一个初始分

        //插入完 返回一个（json格式的字符串）提示
        return CommunityUtil.getJSONString(0,"发布成功");
    }
    //加精
    @RequestMapping(path = "/wonderful",method = RequestMethod.POST)
    @ResponseBody
    public String setwonderful(int id){
        discussPostService.updateStatus(id,1);//1表示加精
        //更新完  我们需要把最新的帖子的数据进行一个同步到elasticSearch，我们好搜索是能搜索到最新的数据
        elasticsearchService.saveDiscussPost(discussPostService.findDiscussPostById(id));
        //可以 再触发一次发帖事件
        Event event=new Event()
                .setTopic(TOPIC_PUBLISH)
                .setUserId(hostHolder.getUser().getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityType(id);
        eventProducer.fireEvent(event);
        //计算帖子的分数
        String postScoreKey = RedisKeyUtil.getPostScoreKey();
        //用Set而不用队列的原因：存在缓存中的数据 无需排序并且要去重-- 可能这个用户点赞由清除又点赞进行多次，那么重复数据算起来没有意义，
        redisTemplate.opsForSet().add(postScoreKey,id);//加精时需要加分，放到缓存里
        return CommunityUtil.getJSONString(0);
    }

    @Autowired
    private UserService userService;
//    //在路径中取到 动态的值 {discussPostId} 然后传给形参，然后查询到结果发给模板，所以 还需要一个model
//    @RequestMapping(path = "/detail/{discussPostId}",method = RequestMethod.GET)
//    public String getDiscussPost(@PathVariable("discussPostId") int discussPostId, Model model){
//        //查询帖子
//        DiscussPost discussPost = discussPostService.findDiscussPostById(discussPostId);
//        model.addAttribute("post",discussPost);
//
//        //discuss_post 表里面只有userId ，但我们显示信息肯定是希望显式用户的名字和其他信息，所以还需要查询user表
//        //用户信息其实可以通过xml文件中通过关联查询来写sql ，也可以直接在controller层写--通过sql查效率高但可能会有冗余和耦合，采用后者差两次效率低但是比较明确 没有冗余
//        // 因为上面查询的帖子中有userId，我可以通过userId去调用userService拿到user 再加到模板中
//        //用户信息
//        User userA = userService.findUserById(discussPost.getUserid());
//        model.addAttribute("user",userA);
//        return "/site/discuss-detail";
//
//    }
    @Autowired
    private CommentService commentService;
    @Autowired
    private LikeService likeService;
    long likeCOUNT;
    int likeStatus;
    //这次查询不仅要查询帖子的数据，还要查询评论，而且评论的数据还要分页
    //只要是实体类型，我们声明在条件（形参）中作为参数，最终spring都会他、把bean存放在model中
    @RequestMapping(path ="/detail/{discussPostId}",method = RequestMethod.GET)
    public String getDiscussPost(@PathVariable("discussPostId") int discussPostId, Model model, Page page){
        //帖子
        DiscussPost post = discussPostService.findDiscussPostById(discussPostId);
        model.addAttribute("post",post);

        //作者
        User user = userService.findUserById(post.getUserid());
        model.addAttribute("user",user);

        //点赞
        likeCOUNT=likeService.findEntityLikeCount(ENTITY_TYPE_POST,discussPostId);
        model.addAttribute("likeCount",likeCOUNT);
        //点赞状态  --如果没有登录 没有用户肯定会出问题，所以我们这得做个判断，如果没登陆状态就为0

         likeStatus=hostHolder.getUser()==null?0:likeService.findEntityLikeStatus(hostHolder.getUser().getId(),ENTITY_TYPE_POST,discussPostId);
        model.addAttribute("likeStatus",likeStatus);
        //除了帖子信息 和 用户信息 还要完善 --评论分页信息
        page.setLimit(5);
        page.setPath("/discuss/detail/"+discussPostId);
        page.setRows(post.getCommentCount());
        //在Community里面定义了 ENTITY_TYPE_POST=1; int ENTITY_TYPE_COMMENT=2;
        //评论：给帖子的评论------回复：给评论的评论 -----评论列表
        List<Comment> commentList = commentService.findCommentsByEntity(
                ENTITY_TYPE_POST, post.getId(), page.getSetOff(), page.getLimit());

        //user_id 和target_id 都要拿到对应表里的信息，放一个id在页面上没什么意义
        //评论Vo列表 --评论显示对象的列表commentVolList
        List<Map<String,Object>> commentVolList=new ArrayList<>();
        if(commentList !=null){
            //遍历得到每一条评论，把这条评论的 评论也得查到，也需要显示
            for (Comment comment : commentList) {
                //一个评论vo
                Map<String,Object> commentVo=new HashMap<>();
                //放入评论
                commentVo.put("comment",comment);
                //放入作者
                commentVo.put("user",userService.findUserById(comment.getUserId()));

                //点赞
                likeCOUNT=likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT,discussPostId);
                commentVo.put("likeCount",likeCOUNT);
                //点赞状态  --如果没有登录 没有用户肯定会出问题，所以我们这得做个判断，如果没登陆状态就为0
                likeStatus=hostHolder.getUser()==null?0:likeService.findEntityLikeStatus(hostHolder.getUser().getId(),ENTITY_TYPE_COMMENT,discussPostId);
                commentVo.put("likeStatus",likeStatus);
                //回复列表   --从0 条到  Integer.MAX_VALUE 条，就是有多少条查多少条，就不分页了
                List<Comment>  replyList=commentService.findCommentsByEntity(
                        ENTITY_TYPE_COMMENT,comment.getId(),0,Integer.MAX_VALUE);

                //要注意 每一个评论都有一个 回复vo列表 需要装到 评论vo中
                //回复VO列表  --和评论VO列表类似，但是 回复VO列表需要多存一个targetId查到的用户 就是回复的用户（回复谁），
                List<Map<String,Object>> replyVoList=new ArrayList<>();
                if(replyList !=null){
                    for (Comment reply : replyList) {
                        //回复vo
                        Map<String,Object> replyVo=new HashMap<>();
                        //放入回复
                        replyVo.put("reply",reply);
                        //放入作者
                        replyVo.put("user",userService.findUserById(reply.getUserId()));
                        //点赞
                        likeCOUNT=likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT,discussPostId);
                        replyVo.put("likeCount",likeCOUNT);
                        //点赞状态  --如果没有登录 没有用户肯定会出问题，所以我们这得做个判断，如果没登陆状态就为0
                        likeStatus=hostHolder.getUser()==null?0:likeService.findEntityLikeStatus(hostHolder.getUser().getId(),ENTITY_TYPE_COMMENT,discussPostId);
                        replyVo.put("likeStatus",likeStatus);
                        //放入 回复的是谁--有可能为0 ，如果为0 就代表没有指定回复谁 只是回复帖子，如果有就把回复的user信息查出来
                        User target = reply.getTargetId() == 0 ? null : userService.findUserById(reply.getTargetId());
                        replyVo.put("target",target);

                        replyVoList.add(replyVo);
                    }
                }
                //要注意 每一个评论都有一个 回复vo列表 需要装到 评论vo中
                commentVo.put("replies",replyVoList);

                //除了回复的列表 还有后面要显示回复的数量
                int replyCount = commentService.findCountByEntity(ENTITY_TYPE_COMMENT, comment.getEntityId());
                commentVo.put("replyCount",replyCount);

                //最后把一条评论中所有要展示的信息都存好了之后 ，这条评论的信息就算完成了 直接放到list中
                commentVolList.add(commentVo);
            }
        }

        //最后把所有评论的所有信息 都给model
        model.addAttribute("comments",commentVolList);



        return "/site/discuss-detail";
    }
    //置顶
    @RequestMapping(path = "/top",method = RequestMethod.POST)
    @ResponseBody
    public String setTop(int id){
        discussPostService.updateType(id,1);//1表示置顶
        //更新完  我们需要把最新的帖子的数据进行一个同步到elasticSearch，我们好搜索是能搜索到最新的数据
        //可以 再触发一次发帖事件
        Event event=new Event()
                .setTopic(TOPIC_PUBLISH)
                .setUserId(hostHolder.getUser().getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityType(id);
        eventProducer.fireEvent(event);
        return CommunityUtil.getJSONString(0);
    }


    //删除
    @RequestMapping(path = "/delete",method = RequestMethod.POST)
    @ResponseBody
    public String setdelete(int id){
        discussPostService.updateStatus(id,2);//1表示删除
        //更新完  我们需要把最新的帖子的数据进行一个同步到elasticSearch，我们好搜索是能搜索到最新的数据
        //可以 再触发一次删帖事件
        Event event=new Event()
                .setTopic(TOPIC_DELETE)
                .setUserId(hostHolder.getUser().getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityType(id);
        eventProducer.fireEvent(event);
        return CommunityUtil.getJSONString(0);
    }





}
